<?php

namespace GordenSong\Laravel\Console\Command;

use GordenSong\Laravel\Exceptions\BladeFileNotFoundException;
use GordenSong\Laravel\Exceptions\FilePutContentException;
use GordenSong\Laravel\Exceptions\TargetFileExistsException;
use GordenSong\Laravel\Templates\TableValidatorTemplate;
use GordenSong\Laravel\Templates\TableValidatorTraitTemplate;
use GordenSong\Laravel\Utils\DatabaseUtil;
use Illuminate\Database\QueryException;
use Illuminate\Filesystem\Filesystem;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;

class GenerateValidatorCommand extends \Illuminate\Console\Command
{
	/**
	 * @var Filesystem $files
	 */
	protected $files;

	/**
	 * The console command name.
	 *
	 * @var string
	 */
	protected $name = 'validator:make {table*} {--connection=mysql}';

	/**
	 * @var string
	 */
	protected $dir = 'app';

	/**
	 * The console command description.
	 *
	 * @var string
	 */
	protected $description = 'Generate one or more table validators';

	/**
	 * @var string
	 */
	protected $existingFactories = '';

	/**
	 * @var array
	 */
	protected $properties = [];

	/**
	 * @var
	 */
	protected $force;
	/**
	 * @var string|null
	 */
	private $connection;

	/**
	 * @param Filesystem $files
	 */
	public function __construct(Filesystem $files)
	{
		parent::__construct();
		$this->files = $files;
	}

	/**
	 * Execute the console command.
	 *
	 * @return void
	 */
	public function handle()
	{
		$this->dir = $this->option('dir');
		$this->connection = $this->option('connection') ?: config('database.default');

		$tables = $this->argument('table');
		if ($tables === ['.']) {
			$tables = DatabaseUtil::allTableNames($this->connection, false);
		}

		if (count($tables) == 0) {
			$this->error('table not exist in this database');
			return;
		}

		foreach ($tables as $table) {
			if ($table === 'migrations') {
				continue;
			}
			try {
				$tableExist = DatabaseUtil::tableExist($this->connection, $table);
				if (!$tableExist) {
					$this->error("Table({$table}) don't exist");
					continue;
				}
			} catch (QueryException $e) {
				$this->error($e->getMessage());
				return;
			}

			$tableValidatorTemplate = new TableValidatorTemplate($table, $this->connection);

			$filename = $tableValidatorTemplate->targetFile();
			if ($this->files->exists($filename)) {
				$this->warn("validator       exists : " . substr($filename, strlen(base_path())));
			} else {
				try {
					$tableValidatorTemplate->output();
					$this->info("validator       created: " . substr($filename, strlen(base_path())));
				} catch (TargetFileExistsException | FilePutContentException | BladeFileNotFoundException $e) {
					$this->error($e->getMessage());
				}
			}

			$validatorTraitTemplate = new TableValidatorTraitTemplate($table, $this->connection);
			try {
				$validatorTraitTemplate->output(true);
				$this->info("validator trait created: " . substr($filename, strlen(base_path())));
			} catch (TargetFileExistsException | FilePutContentException | BladeFileNotFoundException $e) {
				$this->error($e->getMessage());
			}
		}
	}


	/**
	 * Get the console command arguments.
	 *
	 * @return array
	 */
	protected function getArguments(): array
	{
		return [
			['table', InputArgument::REQUIRED | InputArgument::IS_ARRAY, 'Which table to include, "." means all tables, without table prefix', []],
		];
	}

	/**
	 * Get the console command options.
	 *
	 * @return array
	 */
	protected function getOptions(): array
	{
		return [
			['dir', 'D', InputOption::VALUE_OPTIONAL, 'The validator directory', $this->dir],
			['connection', 'C', InputOption::VALUE_OPTIONAL, 'set a connection name'],
		];
	}
}
